/**
 * @name setCanvasWH
 * @description 根据设备分辨率设置canvas宽高和样式宽高
 * @param {HTMLCanvasElement} canvas canvas元素
 * @param {CanvasRenderingContext2D} ctx canvas上下文
 * @param {Number} width 容器宽度
 * @param {Number} height 容器高度
 */
function setCanvasWH(canvas, ctx, width, height) {
  let dpr = window.devicePixelRatio || 1;
  let bsr =
    ctx.webkitBackingStorePixelRatio ||
    ctx.mozBackingStorePixelRatio ||
    ctx.msBackingStorePixelRatio ||
    ctx.oBackingStorePixelRatio ||
    ctx.backingStorePixelRatio ||
    1;
  let ratio = dpr / bsr;
  canvas.width = width;
  canvas.height = height;
  canvas.style.width = width + "px";
  canvas.style.height = height + "px";
}

/**
 * @name getAria
 * @description 得到地图区域大概宽高大小
 * @param {Object} mapInfo 地图信息
 * @returns {Array} 返回地图块的宽高
 */
function getAria(mapInfo) {
  const ALLPOINTS = mapInfo.features
    .map((item) => {
      const {
        geometry: { coordinates },
      } = item;
      const point =
        coordinates[0].length > 1 ? coordinates[0] : coordinates[0][0];
      return point;
    })
    .flat(1);
  const ALLPOINTS_X = ALLPOINTS.map((it) => it[0]);
  const ALLPOINTS_Y = ALLPOINTS.map((it) => it[1]);
  const xMax = Math.max(...ALLPOINTS_X);
  const xMin = Math.min(...ALLPOINTS_X);
  const yMax = Math.max(...ALLPOINTS_Y);
  const yMin = Math.min(...ALLPOINTS_Y);
  const xGap = xMax - xMin;
  const yGap = yMax - yMin;
  return [xGap, yGap];
}
/**
 * @name getAriaAllPoints
 * @description 获取地图所有区域地块点位分组
 * @param {Object} mapInfo 地图信息
 * @returns {Array} 返回地图所有区域地块点位分组
 */
function getAriaAllPoints(mapInfo) {
  return mapInfo.features.map((item) => {
    const {
      geometry: { coordinates },
    } = item;
    const point =
      coordinates[0].length > 1 ? coordinates[0] : coordinates[0][0];
    return point;
  });
}

/**
 * @name getAriaAllTexts
 * @description 获取地图所有区域基本信息
 * @param {Object} mapInfo 地图信息
 * @returns {Array} 返回地图所有区域基本信息
 */

function getAriaAllTexts(mapInfo) {
  return mapInfo.features.map((item) => {
    const { properties } = item;
    return properties;
  });
}

/**
 * @name reversePointY
 * @description 获取当前点相对于指定高度的X轴的镜像坐标
 * @param {Object} point 点坐标
 * @param {Number} tagrline 镜像x轴高度
 * @returns {Array} 返回当前点的镜像坐标
 */
function reversePointY(point, tagrline = 0) {
  const x = point[0] * 12;
  const y = point[1] * 15;
  const gapX = x - tagrline;
  const gapY = y - tagrline;
  const newY = y - gapY * 2;
  return [x - (xGap * 12) / 2, newY + yGap * 15 * 1.8];
}

/**
 * @name render
 * @description 地图块描边与填充函数，渲染地图图形
 * @param {CanvasRenderingContext2D} ctx canvas上下文
 * @param {Array} coordinates 地块坐标数据数组
 */
function render(ctx, coordinates, fillStyle = "rgb(18, 35, 92)") {
  const path = new Path2D();
  coordinates.forEach((it, i) => {
    if (!it.length) return;
    const newPoint = reversePointY(it, 0);
    if (i === 0) {
      path.moveTo(newPoint[0], newPoint[1]);
    } else {
      path.lineTo(newPoint[0], newPoint[1]);
    }
  });
  ctx.beginPath();
  ctx.fillStyle = fillStyle;
  ctx.fill(path);
  ctx.closePath();
  ctx.beginPath();
  ctx.strokeStyle = "#2ab8ff";
  ctx.stroke(path);
  ctx.shadowColor = "rgba(0,54,255, 0.4)";
  ctx.shadowOffsetX = 5;
  ctx.shadowOffsetY = -5;
  ctx.shadowBlur = 5;
  ctx.closePath();
  return path;
}

/**
 * @name renderText
 * @description 地图省市名称填充函数
 * @param {CanvasRenderingContext2D} ctx canvas上下文
 * @param {Object} properties 地图省市信息
 */
function renderText(ctx, properties, font = "14px Arial") {
  ctx.beginPath();
  ctx.fillStyle = "#fff";
  ctx.textAlign = "center";
  ctx.font = font;
  const newPoint = reversePointY(properties.center, 0);
  properties.name && ctx.fillText(properties.name, newPoint[0], newPoint[1]);
  ctx.closePath();
}

/**
 * @interface ShowToolTipParam: {x: Number, y: Number, ctx: CanvasRenderingContext2D, properties: Object, width: Number, height: Number}
 * @param {ShowToolTipParam} param 提示框参数 x,y绘制起始位置 ctx canvas上下文 properties区块基本信息 width,height绘制宽高
 * @name showToolTip
 */
function showToolTip({ x, y, ctx, properties, width, height }) {
  ctx.beginPath();
  ctx.strokeStyle = "#fff";
  ctx.strokeRect(x, y, width, height);
  ctx.closePath();
  ctx.beginPath();
  ctx.fillStyle = "#fff";
  ctx.textAlign = "center";
  ctx.font = "20px Arial";
  const num = Math.floor(Math.random() * 1000);
  ctx.fillText("旅客人数", x + width / 2, y + height / 4);
  properties.name &&
    ctx.fillText(properties.name + ":", x + width / 2, y + height / 1.8);
  ctx.fillText(num + "人", x + width / 2, y + height / 1.2);
  ctx.closePath();
}

/**
 * @interface Point: {x: Number, y: Number}
 * @name isInside
 * @param {CanvasRenderingContext2D} ctx canvas上下文
 * @param {Path2D} path 图像路径
 * @param {Point} point 要判断的点
 * @returns {Boolean} 是否在图形内
 */
function isInside(ctx, path, point) {
  return (
    ctx.isPointInPath(path, point.x, point.y) ||
    ctx.isPointInStroke(path, point.x, point.y)
  );
}

/**
 * @name isPointInPolygon
 * @description 点-多边形相交算法
 * @param {Object} point
 * @param {Array} vertices
 * @returns
 */
function isPointInPolygon(point, vertices) {
  let inside = false;
  for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
    const point_i = reversePointY(vertices[i]);
    const point_j = reversePointY(vertices[j]);
    let xi = point_i[0];
    let yi = point_i[1];
    let xj = point_j[0];
    let yj = point_j[1];

    let intersect =
      yi > point.y != yj > point.y &&
      point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
    if (intersect) inside = !inside;
  }
  return inside;
}
